---
title: "07-API 开放平台项目笔记"
created: 2025-12-02
tags:
- 项目
aliases:
- API 开放平台项目笔记
---
# API 开放平台项目笔记
## 项目介绍
一个提供 API 接口供开发者调用的平台。
用户可以注册登录,开通接口调用权限。用户可以浏览接口并调用,且每次调用会进行统计。
管理员可以发布接口、下线接口、接入接口,以及可视化接口的调用情况、数据。
项目侧重于后端,包含较多的编程技巧和架构设计层面的知识。
## 项目资料
⭐️ API 开放平台项目源码:[源码链接](https://www.code-nav.cn/course/1790979723916521474/section/1790982803160608769?type=#)
(前端:yuapi-frontend,后端:yuapi-backend)
```bash
API 项目前端代码拉取源码启动报错问题: Can not resolve dependence :'echarts-for-react', please install it 解决方案:执行 npm i echarts-for-react@3.0.2 安装 echars 依赖
```
⭐️ 全部直播回放和大纲:[视频链接](https://www.code-nav.cn/course/1790979723916521474/section/1791087226742419457?contentType=video&type=#)
## 第 1 集
主要内容:
1. 项目介绍、业务流程、项目计划、需求分析
2. 数据库表设计
3. 前后端项目初始化(包含 Ant Design Pro 框架最新版本的使用)
4. 前后端代码自动生成(强烈推荐,提高 1000% 的开发效率)
5. 登录页、接口信息页开发
## 需求分析
背景:
1. 前端开发需要用到后台接口
2. 使用现成的系统的功能()
做一个 API 接口平台:
1. 管理员可以对接口信息进行增删改查
2. 用户可以访问前台,查看接口信息
其他要求:
1. 防止攻击(安全性)
2. 不能随便调用(限制、开通)
3. **统计调用次数**
4. 计费
5. 流量保护
6. API 接入
## 业务流程
![[5bf2b96d-ac71-4439-b7a5-2eb0f23d75bb-02c714dd.png]]
## 技术选型
### 前端
- Ant Design Pro
- React
- Ant Design Procomponents
- Umi
- Umi Request(Axios 的封装)
### 后端
- Java Spring Boot
- Spring Boot Starter(SDK 开发)
- Dubbo(RPC)
- Nacos
- Spring Cloud Gateway(网关、限流、日志实现)
## 数据库表设计
### 接口信息表
```sql
-- 接口信息
create table if not exists yuapi.`interface_info`
(
`id` bigint not null auto_increment comment '主键' primary key,
`name` varchar(256) not null comment '名称',
`description` varchar(256) null comment '描述',
`url` varchar(512) not null comment '接口地址',
`requestHeader` text null comment '请求头',
`responseHeader` text null comment '响应头',
`status` int default 0 not null comment '接口状态(0-关闭,1-开启)',
`method` varchar(256) not null comment '请求类型',
`userId` bigint not null comment '创建人',
`createTime` datetime default CURRENT_TIMESTAMP not null comment '创建时间',
`updateTime` datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
`isDelete` tinyint default 0 not null comment '是否删除(0-未删, 1-已删)'
) comment '接口信息';
```
## 项目脚手架
前端:ant design pro 脚手架()
直接下载星球后端代码模板
## 基础功能开发
增删改查、登录功能(通过复制粘贴完成)
前端接口调用:后端使用遵循 openapi 的规范的 swagger 文档,使用前端 Ant Design Pro 框架集成的 oneapi
插件自动生成。
## 第 2 集
单集回放:
主要内容:
1. 开发接口管理前端页面
2. 开发模拟 API 接口
3. 开发调用接口客户端
4. 保证调用的安全性(API 签名认证)
5. 客户端 SDK 的开发(Spring Boot Starter 开发)
## 模拟接口项目
项目名称:yuapi-interface
提供三个不同种类的模拟接口:
1. GET 接口
2. POST 接口(url 传参)
3. POST 接口(Restful)
### 调用接口
几种 HTTP 调用方式:
1. HttpClient
2. RestTemplate
3. 第三方库(OKHTTP、Hutool)
Hutool:
Http 工具类:
## API 签名认证
本质:
1. 签发签名
2. 使用签名(校验签名)
为什么需要?
1. 保证安全性,不能随便一个人调用
2. 适用于无需保存登录态的场景。只认签名,不关注用户登录态。
### 签名认证实现
通过 http request header 头传递参数。
参数 1:accessKey:调用的标识 userA, userB(复杂、无序、无规律)
参数 2:secretKey:密钥(复杂、无序、无规律) **该参数不能放到请求头中**
(类似用户名和密码,区别:ak、sk 是无状态的)
> 大家可以自己写代码来给用户生成 ak、sk
千万不能把密钥直接在服务器之间传递,有可能会被拦截
参数 3:用户请求参数
参数 4:sign
加密方式:对称加密、非对称加密、md5 签名(不可解密)
用户参数 + 密钥 => **签名生成算法(MD5、HMac、Sha1)** => 不可解密的值
abc + abcdefgh => sajdgdioajdgioa
怎么知道这个签名对不对?
**服务端用一模一样的参数和算法去生成签名,只要和用户传的的一致,就表示一致。**
**怎么防重放?**
参数 5:加 nonce 随机数,只能用一次
服务端要保存用过的随机数
参数 6:加 timestamp 时间戳,校验时间戳是否过期。
**API 签名认证是一个很灵活的设计,具体要有哪些参数、参数名如何一定要根据场景来。(比如 userId、appId、version、固定值等)**
思考:难道开发者每次调用接口都要自己写签名算法?
## 开发简单易用的 SDK(简历加分项)
项目名:yuapi-client-sdk
### 为什么需要 Starter?
理想情况:开发者只需要关心调用哪些接口、传递哪些参数,就跟调用自己写的代码一样简单。
开发 starter 的好处:开发者引入之后,可以直接在 application.yml 中写配置,自动创建客户端
### Starter 开发流程
初始化,环境依赖(一定要移除 build):
spring-boot-configuration-processor 的作用是自动生成配置的代码提示
```xml
org.springframework.boot
spring-boot-autoconfigure
org.springframework.boot
spring-boot-configuration-processor
true
org.projectlombok
lombok
true
```
编写配置类(启动类):
```java
@Configuration
@ConfigurationProperties(prefix = "yuapi.client")
@Data
@ComponentScan
public class YuApiClientConfig {
/**
* appId
*/
private String appId;
/**
* 秘钥
*/
private String appSecret;
/**
* 用户 id
*/
private String userId;
@Bean
public YuApiClient yuApiClient() {
return new YuApiClient(appId, appSecret, userId);
}
}
```
注册配置类,resources/META\_INF/spring.factories 文件:
```properties
# spring boot starter
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.yupi.yuapiclientsdk.YuApiClientConfig
```
mvn install 打包代码为本地依赖包
创建新项目(复用 server 项目)、测试
小作业:把打好的包发到 maven 仓库中
## 第 3 集
主要内容:
1. 开发接口发布 / 下线的功能
2. 开发浏览接口、查看接口文档、申请签名功能
3. 开发在线调试功能
## 功能开发
### 接口发布 / 下线的功能
权限控制:仅管理员可操作。
#### 业务逻辑
发布接口:
1. 校验该接口是否存在
2. 判断该接口是否可以调用
3. 修改接口数据库中的状态字段为 1
下线接口:
1. 校验该接口是否存在
2. 修改接口数据库中的状态字段为 0
### 前端浏览接口
### 查看接口文档
思路:动态路由,用 url 来传递 id,加载不同的接口信息
### 申请签名
用户在注册成功时,自动分配 accessKey、secretKey
### 在线调用
请求参数的类型(直接用 json 类型,更灵活):
```json
[ {"name": "username", "type": "string"} ]
```
先跑通整个接口流程,后续可以针对不同的请求头或者接口类型来设计界面和表单,给用户更好的体验。(可以参考 swagger、postman、knife4j)
#### 调用流程
使用上述流程:
![[44ef9fa7-78d3-464b-be57-5909521d8b71-e76756f1.png]]
流程:
1. 前端将用户输入的请求参数和要测试的接口 id 发给平台后端
2. (在调用前可以做一些校验)
3. 平台后端去调用模拟接口
## todo
判断该接口是否可以调用时由固定方法名改为根据测试地址来调用
用户测试接口固定方法名改为根据测试地址来调用
模拟接口改为从数据库校验 akey
## 第 4 集
主要内容:
1. 开发接口调用次数统计功能
2. 优化整个系统的架构 - API 网关详解
1. 网关是什么?
2. 网关的作用?
3. 网关的应用场景及实现?
4. 结合业务去应用网关
## 接口调用次数统计
需求:
1. 用户每次调用接口成功,次数 + 1
2. 给用户分配或者用户自主申请接口调用次数
业务流程:
1. 用户调用接口(之前已完成)
2. 修改数据库,调用次数 +1
设计库表:
哪个用户?哪个接口?
用户 => 接口(多对多)
用户调用接口关系表:
```sql
-- 用户调用接口关系表
create table if not exists yuapi.`user_interface_info`
(
`id` bigint not null auto_increment comment '主键' primary key,
`userId` bigint not null comment '调用用户 id',
`interfaceInfoId` bigint not null comment '接口 id',
`totalNum` int default 0 not null comment '总调用次数',
`leftNum` int default 0 not null comment '剩余调用次数',
`status` int default 0 not null comment '0-正常,1-禁用',
`createTime` datetime default CURRENT_TIMESTAMP not null comment '创建时间',
`updateTime` datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
`isDelete` tinyint default 0 not null comment '是否删除(0-未删, 1-已删)',
) comment '用户调用接口关系';
```
开发步骤:
1. 开发基本增删改查(给管理员用)
2. 开发用户调用接口次数 +1 的功能(service)
### 问题
如果每个接口的方法都写调用次数 + 1,是不是比较麻烦?
致命问题:接口开发者需要自己去添加统计代码
![[f2a17383-6808-4a7b-b163-3727179348b5-078de92e.png]]
使用 AOP 切面的优点:独立于接口,在每个接口调用后统计次数 + 1
AOP 切面的缺点:只存在于单个项目中,如果每个团队都要开发自己的模拟接口,那么都要写一个切面
## 网关
什么是网关?理解成火车站的检票口, **统一** 去检票。
### 作用
统一去进行一些操作、处理一些问题。
比如:
1. 路由
2. 负载均衡
3. 统一鉴权
4. 跨域
5. 统一业务处理(缓存)
6. 访问控制
7. 发布控制
8. 流量染色
9. 接口保护
1. 限制请求
2. 信息脱敏
3. 降级(熔断)
4. 限流:学习令牌桶算法、学习漏桶算法,学习一下 RedisLimitHandler
5. 超时时间
10. 统一日志
11. 统一文档
#### 路由
起到转发的作用,比如有接口 A 和接口 B,网关会记录这些信息,根据用户访问的地址和参数,转发请求到对应的接口(服务器 / 集群)
/a => 接口A
/b => 接口B
#### 负载均衡
在路由的基础上
/c => 服务 A / 集群 A(随机转发到其中的某一个机器)
uri 从固定地址改成 lb:xxxx
#### 统一处理跨域
网关统一处理跨域,不用在每个项目里单独处理
#### 发布控制
灰度发布,比如上线新接口,先给新接口分配 20% 的流量,老接口 80%,再慢慢调整比重。
#### 流量染色
给请求(流量)添加一些标识,一般是设置请求头中,添加新的请求头
全局染色:
#### 统一接口保护
1. 限制请求:
2. 信息脱敏:
3. 降级(熔断):
4. 限流:
5. 超时时间:
6. 重试(业务保护):
#### 统一业务处理
把一些每个项目中都要做的通用逻辑放到上层(网关),统一处理,比如本项目的次数统计
#### 统一鉴权
判断用户是否有权限进行操作,无论访问什么接口,我都统一去判断权限,不用重复写。
#### 访问控制
黑白名单,比如限制 DDOS IP
#### 统一日志
统一的请求、响应信息记录
#### 统一文档
将下游项目的文档进行聚合,在一个页面统一查看
建议用:
## 网关的分类
1. 全局网关(接入层网关):作用是负载均衡、请求日志等,不和业务逻辑绑定
2. 业务网关(微服务网关):会有一些业务逻辑,作用是将请求转发到不同的业务 / 项目 / 接口 / 服务
参考文章:
## 网关实现
1. Nginx(全局网关)、Kong 网关(API 网关,Kong:),编程成本相对高一点
2. Spring Cloud Gateway(取代了 Zuul)性能高、可以用 Java 代码来写逻辑,适于学习
网关技术选型:
## Spring Cloud Gateway 用法
去看官网:
官方文档:
### 核心概念
路由(根据什么条件,转发请求到哪里)
断言:一组规则、条件,用来确定如何转发路由
过滤器:对请求进行一系列的处理,比如添加请求头、添加请求参数
请求流程:
1. 客户端发起请求
2. Handler Mapping:根据断言,去将请求转发到对应的路由
3. Web Handler:处理请求(一层层经过过滤器)
4. 实际调用服务
![[3c159313-f421-4797-be69-9febba64fe7d-4eef5654.png]]
### 两种配置方式
1. 配置式(方便、规范)
1. 简化版
2. 全称版
2. 编程式(灵活、相对麻烦)
### 建议开启日志
```yaml
logging: level: org: springframework: cloud: gateway: trace
```
### 断言
1. After 在 xx 时间之后
2. Before 在 xx 时间之前
3. Between 在 xx 时间之间
4. 请求类别
5. 请求头(包含 Cookie)
6. 查询参数
7. 客户端地址
8. **权重**
### 过滤器
基本功能:对请求头、请求参数、响应头的增删改查
1. 添加请求头
2. 添加请求参数
3. 添加响应头
4. 降级
5. 限流
6. 重试
引入:
```xml
org.springframework.cloud spring-cloud-starter-circuitbreaker-reactor-resilience4j
```
小作业:
通过阅读源码: 来了解
gateway 编程式开发
## 第 5 集
主要内容:
1. 实现统一的接口鉴权和计费(API 网关实践)
## 要用到的特性
1. 路由(转发请求到模拟接口项目)
2. ~~负载均衡(需要用到注册中心)~~
3. 统一鉴权(accesskey, secretKey)
4. ~~跨域~~
5. 统一业务处理(每次请求接口后,接口调用次数 +1)
6. 访问控制(黑白名单)
7. ~~发布控制~~
8. 流量染色(记录请求是否为网关来的)
9. ~~接口保护~~
1. 限制请求
2. 信息脱敏
3. 降级(熔断)
4. 限流:学习令牌桶算法、学习漏桶算法,学习一下 RedisLimitHandler
5. 超时时间
10. 统一日志(记录每次的请求和响应日志)
11. ~~统一文档~~
## 业务逻辑
1. 用户发送请求到 API 网关
2. 请求日志
3. (黑白名单)
4. 用户鉴权(判断 ak、sk 是否合法)
5. 请求的模拟接口是否存在?
6. **请求转发,调用模拟接口**
7. 响应日志
8. 调用成功,接口调用次数 + 1
9. 调用失败,返回一个规范的错误码
## 具体实现
### 1. 请求转发
使用前缀匹配断言:
所有路径为:/api/ **的请求进行转发,转发到** [**http://localhost:8123/api/**](http://localhost:8123/api/)
比如请求网关:
转发到:
```yaml
spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=source, yupi
routes:
- id: api_route
uri: http://localhost:8123
predicates:
- Path=/api/**
```
### 2. 编写业务逻辑
使用了 GlobalFilter(编程式),全局请求拦截处理(类似 AOP)
因为网关项目没引入 MyBatis 等操作数据库的类库,如果该操作较为复杂,可以由 backend 增删改查项目提供接口,我们直接调用,不用再重复写逻辑了。
- HTTP 请求(用 HTTPClient、用 RestTemplate、Feign)
- RPC(Dubbo)
### 问题
预期是等模拟接口调用完成,才记录响应日志、统计调用次数。
但现实是 chain.filter 方法立刻返回了,直到 filter 过滤器 return 后才调用了模拟接口。
原因是:chain.filter 是个异步操作,理解为前端的 promise
解决方案:利用 response 装饰者,增强原有 response 的处理能力
参考博客:(以这个为主)
其他参考:
-
- [https://blog.csdn.net/weixin\_43933728/article/details/121359727](https://blog.csdn.net/weixin_43933728/article/details/121359727?spm=1001.2014.3001.5501)
-
-
## 第 6 集
主要内容:
1. 实现统一的接口鉴权和计费(RPC、Dubbo 讲解)
## 网关业务逻辑
问题:网关项目比较纯净,没有操作数据库的包、并且还要调用我们之前写过的代码?复制粘贴维护麻烦
理想:直接请求到其他项目的方法
### 怎么调用其他项目的方法?
1. 复制代码和依赖、环境
2. HTTP 请求(提供一个接口,供其他项目调用)
3. RPC
4. 把公共的代码打个 jar 包,其他项目去引用(客户端 SDK)
### HTTP 请求怎么调用?
1. 提供方开发一个接口(地址、请求方法、参数、返回值)
2. 调用方使用 HTTP Client 之类的代码包去发送 HTTP 请求
## RPC
作用:像调用本地方法一样调用远程方法。
和直接 HTTP 调用的区别:
1. 对开发者更透明,减少了很多的沟通成本。
2. RPC 向远程服务器发送请求时,未必要使用 HTTP 协议,比如还可以用 TCP / IP,性能更高。(内部服务更适用)
RPC 调用模型:
![[415e319e-e585-4243-9f8a-a9767fbb28ad-19e3a6c6.png]]
## Dubbo 框架(RPC 实现)
其他 RPC 框架:GRPC、TRPC
最好的学习方式:阅读官方文档
两种使用方式:
1. Spring Boot 代码(注解 + 编程式):写 Java 接口,服务提供者和消费者都去引用这个接口
2. IDL(接口调用语言):创建一个公共的接口定义文件,服务提供者和消费者读取这个文件。优点是跨语言,所有的框架都认识
底层是 Triple 协议:
### 示例项目学习
zookeeper 注册中心:通过内嵌的方式运行,更方便
最先启动注册中心,先启动服务提供者,再启动服务消费者
### 整合运用
1. backend 项目作为服务提供者,提供 3 个方法:
1. 实际情况应该是去数据库中查是否已分配给用户
2. 从数据库中查询模拟接口是否存在,以及请求方法是否匹配(还可以校验请求参数)
3. 调用成功,接口调用次数 + 1 invokeCount
2. gateway 项目作为服务调用者,调用这 3 个方法
建议大家用 Nacos!
整合 Nacos 注册中心:
注意:
1. 服务接口类必须要在同一个包下,建议是抽象出一个公共项目(放接口、实体类等)
2. 设置注解(比如启动类的 EnableDubbo、接口实现类和 Bean 引用的注解)
3. 添加配置
4. 服务调用项目和提供者项目尽量引入相同的依赖和配置
```xml
org.apache.dubbo
dubbo
3.0.9
com.alibaba.nacos
nacos-client
2.1.0
```
## 第 7 集
主要内容:
1. 开发抽象公共服务
2. 实现网关核心业务流程
3. 开发管理员接口分析功能
4. 上线分析和扩展
## 梳理网关业务逻辑
以下操作可以复用:
1. 实际情况应该是去数据库中查是否已分配给用户秘钥(ak、sk是否合法)
1. 先根据 accessKey 判断用户是否存在,查到 secretKey
2. 对比 secretKey 和用户传的加密后的 secretKey 是否一致
2. 从数据库中查询模拟接口是否存在,以及请求方法是否匹配(还可以校验请求参数)
3. 调用成功,接口调用次数 + 1 invokeCount
## 临时问题:如何获取接口转发服务器的地址
思路:网关启动时,获取所有的接口信息,维护到内存的 hashmap 中;有请求时,根据请求的 url 路径或者其他参数(比如 host 请求头)来判断应该转发到哪台服务器、以及用于校验接口是否存在
## 抽象公共服务
项目名:yuapi-common
目的是让方法、实体类在多个项目间复用,减少重复编写。
服务抽取:
1. 数据库中查是否已分配给用户秘钥(根据 accessKey 拿到用户信息,返回用户信息,为空表示不存在)
2. 从数据库中查询模拟接口是否存在(请求路径、请求方法、请求参数,返回接口信息,为空表示不存在)
3. 接口调用次数 + 1 invokeCount(accessKey、secretKey(标识用户),请求接口路径)
步骤:
1. 新建干净的 maven 项目,只保留必要的公共依赖
2. 抽取 service 和实体类
3. install 本地 maven 包
4. 让服务提供者引入 common 包,测试是否正常运行
5. 让服务消费者引入 common 包
## 统计分析功能
### 需求
各接口的总调用次数占比(饼图)取调用最多的前 3 个接口,从而分析出哪些接口没有人用(降低资源、或者下线),高频接口(增加资源、提高收费)。
用饼图展示。
### 实现
#### 前端
强烈推荐用现成的库!!!
比如:
- ECharts:[https://echarts.apache.org/zh/index.html(推荐)](https://echarts.apache.org/zh/index.html%EF%BC%88%E6%8E%A8%E8%8D%90%EF%BC%89)
- AntV:[https://antv.vision/zh(推荐)](https://antv.vision/zh%EF%BC%88%E6%8E%A8%E8%8D%90%EF%BC%89)
- BizCharts
用法贼简单!
1. 看官网
2. 找到快速入门、按文档去引入库
3. 进入示例页面
4. 找到你要的图
5. 在线调试
6. 复制代码
7. 改为真实数据
如果是 React 项目,用这个库:
### 后端
写一个接口,得到下列示例数据:
接口 A:2次
接口 B:3次
步骤:
1. SQL 查询调用数据:select interfaceInfoId, sum(totalNum) as totalNum from user\_interface\_info
group by interfaceInfoId order by totalNum desc limit 3;
2. 业务层去关联查询接口信息
## 上线计划
前端:参考之前用户中心或伙伴匹配系统的上线方式
后端:
- backend 项目:web 项目,部署 spring boot 的 jar 包(对外的)
- gateway 网关项目:web 项目,部署 spring boot 的 jar 包(对外的)
- interface 模拟接口项目:web 项目,部署 spring boot 的 jar 包(不建议对外暴露的)
**关键:网络必须要连通**
如果自己学习用:单个服务器部署这三个项目就足够。
如果你是搞大事,多个服务器建议在 **同一内网** ,内网交互会更快、且更安全。
## 扩展思路
### 1. 用户可以申请更换签名
### 2. 怎么让其他用户也上传接口?
需要提供一个机制(界面),让用户输入自己的接口 host(服务器地址)、接口信息,将接口信息写入数据库。
可以在 interfaceInfo 表里加个 host 字段,区分服务器地址,让接口提供者更灵活地接入系统。
将接口信息写入数据库之前,要对接口进行校验(比如检查他的地址是否遵循规则,测试调用),保证他是正常的。
将接口信息写入数据库之前遵循咱们的要求(并且使用咱们的 sdk),
在接入时,平台需要测试调用这个接口,保证他是正常的。
### 3. 网关校验是否还有调用次数
需要考虑并发问题,防止瞬间调用超额。
### 4. 网关优化
比如增加限流 / 降级保护,提高性能等。还可以考虑搭配 Nginx 网关使用。
### 5. 功能增强
可以针对不同的请求头或者接口类型来设计前端界面和表单,便于用户调用,获得更好的体验。
可以参考 swagger、postman、knife4j 的页面。
---
**项目分区导航**:⬅️ [[06-API 开放平台快速运行|06-API 开放平台快速运行]] | 07-API 开放平台项目笔记 | ➡️ [[08-项目笔记(一)|08-项目笔记(一)]]